package com.yellow.car.impl;

import com.yellow.car.api.DispatchApi;
import com.yellow.car.api.PathApi;
import com.yellow.car.api.StationApi;
import com.yellow.car.api.TruckApi;
import com.yellow.car.entity.CyclingTruckCar;
import com.yellow.car.entity.Station;
import com.yellow.car.entity.Truck;
import com.yellow.car.request.PathQueryRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class DispatchApiImpl implements DispatchApi {
    private static List<CyclingTruckCar> cyclingEndTimeTrunk = new ArrayList<>();
    @Resource
    PathApi pathApi;
    @Resource
    StationApi stationApi;
    @Resource
    TruckApi truckApi;

    @Override
    public void dispatch(Station startStation, Station endStation, Integer total, Integer stationNum) {
        Integer cyclingYellowCarNum = getCyclingYellowCarNum(startStation, endStation, total, stationNum);
        if (cyclingYellowCarNum <= 0) {
            log.info("当前两个站点车都比较少,暂时不调度");
            return;
        }
        getCyclingTruckCar(startStation, endStation, cyclingYellowCarNum);
    }

    @Override
    public List<CyclingTruckCar> getCyclingTruckList() {
        return cyclingEndTimeTrunk;
    }

    @Override
    public void removeCyclingTruckList(CyclingTruckCar cyclingTruckCar) {
        cyclingEndTimeTrunk.remove(cyclingTruckCar);
    }

    private void getCyclingTruckCar(Station startStation, Station endStation, Integer cyclingYellowCarNum) {
        List<Truck> startTruckList = startStation.getTruckList();
        if (!CollectionUtils.isEmpty(startTruckList)) {
            Truck truck = startTruckList.get(0);
            Boolean flag = stationApi.reduceTruckByStationName(startStation.getStationName(), truck);
            Boolean carFlag = stationApi.reduceByStationName(startStation.getStationName(), cyclingYellowCarNum);
            if (flag && carFlag) {
                PathQueryRequest request = new PathQueryRequest();
                request.setStartStation(startStation.getStationName());
                request.setEndStation(endStation.getStationName());
                int[][] path = pathApi.getPath(request);
                setCyclingTruckCar(startStation, endStation, cyclingYellowCarNum, path, truck);
            }
        } else {
            Station station = stationApi.getFreeTruckStation();
            if (station == null || CollectionUtils.isEmpty(station.getTruckList())) {
                log.info("没有站点有空闲的车,等待下次调度");
                return;
            }
            Truck truck = station.getTruckList().get(0);
            Boolean flag = stationApi.reduceTruckByStationName(station.getStationName(), truck);
            if (flag) {
                PathQueryRequest request = new PathQueryRequest();
                request.setStartStation(station.getStationName());
                request.setEndStation(startStation.getStationName());
                int[][] path = pathApi.getPath(request);
                setCyclingTruckCar(station, startStation, 0, path, truck);
            }
        }
    }

    private void setCyclingTruckCar(Station startStation, Station endStation, Integer yellowCarNum, int[][] path, Truck truck) {
        CyclingTruckCar cyclingTruckCar = new CyclingTruckCar();
        cyclingTruckCar.setTruck(truck);
        cyclingTruckCar.setYellowCarNum(yellowCarNum);
        cyclingTruckCar.setStartStationName(startStation.getStationName());
        cyclingTruckCar.setEndStationName(endStation.getStationName());
        cyclingTruckCar.setCyclingEndTime(getCyclingTime(path, truck));
        cyclingEndTimeTrunk.add(cyclingTruckCar);
    }

    private Long getCyclingTime(int[][] path, Truck trunk) {
        long currentTime = System.currentTimeMillis();
        double speed = truckApi.getSpeed(trunk);
        long needTime = (long) (path.length * speed * 1000);
        return currentTime + needTime;
    }

    private Integer getCyclingYellowCarNum(Station startStation, Station endStation, Integer total, Integer stationNum) {
        Integer avgNum = total / stationNum;
        Integer startNum = startStation.getCarNum();
        Integer cyclingYellowCarNum = startNum - avgNum;
        if (cyclingYellowCarNum >= 20) {
            return 20;
        }
        if (cyclingYellowCarNum > 0) {
            return cyclingYellowCarNum;
        }
        return 0;
    }

}
